<?php

namespace app\common\service;

use app\common\exception\BusinessException;
use think\facade\Cache;

class ReqLimitService
{
    /**
     * key
     * @var string
     */
    private $key = 'user_req_limit';

    /**
     * ttl
     * @var int
     */
    private $ttl = 3600 * 7;

    /**
     * uid
     * @var int
     */
    private $uid = 0;

    /**
     * check
     * @param $uid
     * @throws BusinessException
     */
    public function check($uid)
    {
        $this->uid = $uid;
        $this->checkReqData();
    }

    /**
     * checkReqData
     * @throws BusinessException
     */
    private function checkReqData()
    {
        // now time
        $time = time();

        // init key
        $reqTimeKey = $this->key . '_time_' . $this->uid;

        // get uid req data
        $reqLogData = json_decode(Cache::get($reqTimeKey), true);
        if (!$reqLogData) {
            $reqLogData = [
                's_time' => $time, //first request time
                'e_time' => $time, //last request time
                'time_count' => 0,
                'request_count' => 0,
            ];
        } else {
            // check time count limit
            $req_time_count = $reqLogData['time_count'];
            if ($req_time_count > 5) {
                $this->punishUser();
                return;
            }

            // check request count limit
            $req_count = $reqLogData['request_count'];
            if ($req_count > 100) {
                $this->punishUser();
                return;
            }

            // check time can log
            $e_time = $reqLogData['e_time'];
            if (($time - $e_time) <= 1) {
                $reqLogData['time_count']++;
            }
        }

        // save uid req date
        $reqLogData['e_time'] = $time;
        $reqLogData['request_count']++;
        Cache::set($reqTimeKey, json_encode($reqLogData), $this->ttl);
    }

    /**
     * punishUser
     * @return void
     * @throws BusinessException
     */
    protected function punishUser()
    {
        $userService = new UserService();
        $userService->deductScoreToUid($this->uid, 30, '请求限制费');
    }
}